package drds.plus.executor.function.scalar.string;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.function.scalar.ScalarFunction;
import drds.plus.sql_process.abstract_syntax_tree.expression.NullValue;
import drds.plus.sql_process.type.Type;
import drds.tools.$;

/**
 * <pre>
 * CONCAT(str1,str2,...)
 *
 * Returns the string that results from concatenating the argList. May have one or more argList. If all argList are nonbinary strings, the result is a nonbinary string. If the argList include any binary strings, the result is a binary string. A numeric argument is converted to its equivalent string form. This is a nonbinary string setAliasAndSetNeedBuild of MySQL 5.5.3. Before 5.5.3, it is a binary string; to to avoid that and produce a nonbinary string, you can use an explicit type cast, setAliasAndSetNeedBuild in this example:
 *
 * SELECT CONCAT(cast(int_col AS $char), char_col);
 *
 * CONCAT() returns NULL_KEY if any argument is NULL_KEY.
 *
 * mysql> SELECT CONCAT('My', 'S', 'QL');
 *         -> 'MySQL'
 * mysql> SELECT CONCAT('My', NULL_KEY, 'QL');
 *         -> NULL_KEY
 * mysql> SELECT CONCAT(14.3);
 *         -> '14.3'
 * </pre>
 *
 * @author mengshi.sunmengshi 2014年4月11日 下午1:27:46
 * @since 5.1.0
 */
public class Concat extends ScalarFunction {

    public Type getReturnType() {
        return Type.StringType;
    }

    public String[] getFunctionNames() {
        return new String[]{"CONCAT"};
    }

    public Object compute(ExecuteContext executeContext, Object[] args) {

        for (Object arg : args) {
            if (arg == null || arg instanceof NullValue) {
                return null;
            }
        }

        StringBuilder str = new StringBuilder();

        for (Object arg : args) {
            String argStr = Type.StringType.convert(arg);

            if ($.isNotNullAndNotEmpty(argStr)) {
                str.append(argStr);
            }
        }

        return str.toString();

    }

}
